/**
 * @AStrutst2Init.as
 * 
 * @author sodaChen mail:asframe@163.com
 * @version 1.0
 * <br>Copyright (C), 2012 ASFrame.com
 * <br>This program is protected by copyright laws.
 * <br>Program Name:ASFrame AStruts2
 * <br>Date:2012-5-10
 */
package com.asframe.astruts2
{
	import com.asframe.astruts2.beans.AstrutsBeans;
	import com.asframe.astruts2.beans.MediatorBean;
	import com.asframe.astruts2.beans.NoticeFilterBean;
	import com.asframe.astruts2.beans.SystemBean;
	import com.asframe.astruts2.beans.ViewBean;
	import com.asframe.astruts2.config.ConfigParse;
	import com.asframe.astruts2.context.AStrutsContext;
	import com.asframe.astruts2.context.AStrutsData;
	import com.asframe.astruts2.context.IAStrutsContext;
	import com.asframe.astruts2.controller.InitViewMediator;
	import com.asframe.astruts2.controller.ResNextLoader;
	import com.asframe.astruts2.controller.ViewDrawSwap;
	import com.asframe.astruts2.event.InitViewMediatorEvent;
	import com.asframe.astruts2.interfaces.IInitViewEnd;
	import com.asframe.astruts2.interfaces.IMediatorCreateEvent;
	import com.asframe.astruts2.interfaces.IRootContainer;
	import com.asframe.astruts2.interfaces.impl.Injection;
	import com.asframe.astruts2.metadata.CheckMetadata;
	import com.asframe.astruts2.metadata.MetadataConst;
	import com.asframe.astruts2.proxy.MediatorObserverProxy;
	import com.asframe.collections.lists.ArrayList;
	import com.asframe.collections.lists.IList;
	import com.asframe.load.ILoader;
	import com.asframe.load.LoadData;
	import com.asframe.load.TextLoader;
	import com.asframe.load.multi.IMultiLoader;
	import com.asframe.load.multi.SameLoader;
	import com.asframe.loading.ILoading;
	import com.asframe.loading.IMultilLoading;
	import com.asframe.pattern.observer.ISubjects;
	import com.asframe.pattern.observer.Subjects;
	import com.asframe.ref.Metadata;
	import com.asframe.ref.MetadataContainer;
	import com.asframe.ref.Method;
	import com.asframe.ref.Type;
	import com.asframe.ref.Variable;
	import com.asframe.utils.ClassUtils;

	/**
	 * AStrtust2系统初始化的对象，系统使用前必须调用该对象 
	 * @author soda.Chen
	 * 
	 */	
	public class AStrutst2Init
	{
		/** 应用根容器对象 **/
		private var root					:IRootContainer;
		private var viewEventList			:IList;
		/** 需要即时初始化的数量 **/
		private var initCount				:int;
		private var onComplete				:Function;
		private var initViewList			:IList;
		private var astrutsData				:AStrutsData;
		private var astrustBean				:AstrutsBeans;
		private var loader					:TextLoader;
		
		public function AStrutst2Init(root:IRootContainer,loader:IMultiLoader = null,loading:IMultilLoading = null)
		{
			this.root = root;
			viewEventList = new ArrayList();
			initViewList = new ArrayList();
			//检测是否支持框架所使用到的标签
			new CheckMetadata();
			
			astrutsData = new AStrutsData();
			var subjects:ISubjects = new Subjects();
			astrutsData.subjects = subjects;
			astrutsData.injector = new Injection();
			astrutsData.mediatorCreateEvents = new ArrayList();
			astrutsData.systemBean = new SystemBean();
			astrutsData.root = root;
			astrutsData.viewHandlers = [];
			astrutsData.viewHandlers.push(new ViewDrawSwap());
			if(loader == null)
			{
				loader = new SameLoader();
				//设置astruts的特殊加载解析
				loader.setNextLoader(new ResNextLoader());
				//以后如果有加载，还需要增加解密
			}
		}
		
		public function addMediatorCreateEvent(mediatorEvent:IMediatorCreateEvent):void
		{
			astrutsData.mediatorCreateEvents.add(mediatorEvent);
		}
		/**
		 * 添加一个view的初始化结束处理接口 
		 * @param initViewEnd
		 * 
		 */		
		public function addInitViewEnd(initViewEnd:IInitViewEnd):void
		{
			astrutsData.initViewEnds.push(initViewEnd);
		}
		/**
		 * 初始化一个Astruts2的 AStrutsContext
		 * @return 
		 * 
		 */		
		public function initContext():IAStrutsContext
		{
			var context:IAStrutsContext = new AStrutsContext(astrutsData);
			astrutsData.context = context;
			return context;
		}
		/**
		 * 初始化AStruts，当需要加载Astruts2的配置文件时，请使用该方法 
		 * @param xml
		 * @param onComplete
		 * @return 
		 * 
		 */		
		public function initAstruts(onComplete:Function, xml:* = null):IAStrutsContext
		{
			this.onComplete = onComplete;
			var context:IAStrutsContext = initContext();
			if(xml == null)
			{
				//系统的默认xml文件路径
				xml = Astruts2Const.CONFIG_PATH;
			}
			if(xml is String)
			{
				loader = new TextLoader();
				//增加随机数，确保每次是最新的
				loader.load(xml + "?v=" + int(Math.random() * 100000),function onLoaderXML(loadData:LoadData):void
				{
					parseConfig(context,XML(loadData.data),onComplete);
					loadData.loader.dispose();
					loader = null;
				});
			}
			else if(xml is XML)
			{
				parseConfig(context,xml,onComplete);
			}
			else
			{
				throw new Error("AStrtust2的配置信息必须是XML路径或者XML文件，传入的是:" + xml);
			}
			return context;
		}
		private function parseConfig(context:IAStrutsContext,xml:XML,onComplete:Function):void
		{
			astrustBean = new ConfigParse().configParse(xml);
			//对各种数据进行处理
			var views:Array = astrustBean.views;
			astrutsData.systemBean = astrustBean.systems;
			
			var beforeSujects:ISubjects = null;
			//处理过滤器
			for each (var filterBean:NoticeFilterBean in astrustBean.noticeFilters) 
			{
				if(filterBean.lazy)
				{
					//延迟处理
				}
				else
				{
//					var noticeFilter:Object = RefUtils.refObject(filterBean.clazz);
					//是前还是后
				}
			}
			
			for each (var viewBean:ViewBean in views) 
			{
				if(initViewBean(viewBean,astrutsData,onViewInitEvent))
				{
					initCount++;
				}
			}
			//全部延迟
			if(initCount == 0)
			{
				onComplete();
			}
		}
		/**
		 * 对一个ViewBean配置数据进行初始化，立刻初始化则返回true，否则是false
		 * @param viewBean View的相关信息
		 * @param astrutsData Astruts应用的相关数据对象
		 * @param onViewInitEvent view初始化完成事件
		 * @return 立刻初始化则返回true，否则是false 
		 */		
		public static function initViewBean(viewBean:ViewBean,astrutsData:AStrutsData,onViewInitEvent:Function):Boolean
		{
			//延迟处理，进行相关的事件监听(这里主要是处理，一旦收到相关的主题的通知，则立马进行相关的初始化)
			if(viewBean.lazy)
			{
				var mediatorClass:Class = null;
				var mediatorType:Type = null;
				var metadata:Metadata = null;
				var mediatorProxy:MediatorObserverProxy = new MediatorObserverProxy(viewBean,astrutsData); 
				for each (var mediatorBean:MediatorBean in viewBean.mediators) 
				{
					mediatorClass = mediatorBean.mediatorClass;
					if(mediatorClass == null)
					{
						mediatorClass = ClassUtils.forName(mediatorBean.clazz);
						mediatorBean.mediatorClass = mediatorClass;
					}
					mediatorType = mediatorBean.mediatorType;
					if(mediatorType == null)
					{
						mediatorType = Type.forClass(mediatorClass);
						mediatorBean.mediatorType = mediatorType;
					}
					//增加感兴趣的通知的注册,主要是进行标签处理之类的,查看是否有监听的方法
					metadataNotice(viewBean,mediatorType.staticVariables,mediatorProxy,astrutsData.subjects);
					metadataNotice(viewBean,mediatorType.staticConstants,mediatorProxy,astrutsData.subjects);
					//方法中配置有notcie的
					metadataNotice(viewBean,mediatorType.methods,mediatorProxy,astrutsData.subjects);
					
					//配置文件中指定的主题
					for each (var noticeStr:String in mediatorBean.notices) 
					{
						viewBean.addObserver(noticeStr,mediatorProxy);
						astrutsData.subjects.addObserver(noticeStr,mediatorProxy);
					}
				}
				return false;
			}
			else
			{
				//立刻进行初始化,同时监听初始化完成事件
				var initViewMediator:InitViewMediator = new InitViewMediator(viewBean,astrutsData);
				initViewMediator.addEventListener(InitViewMediatorEvent.INIT_OVER,onViewInitEvent);
				initViewMediator.initViewMediator();
				return true;
			}
		}
		/**
		 * 添加一个静态的通知（延迟初始化的Mediator） 
		 * @param viewBean
		 * @param variables
		 * @param mediatorProxy
		 * @param subjects
		 * 
		 */		
		public static function metadataNotice(	viewBean:ViewBean,
											   	metadatas:Array,
												mediatorProxy:MediatorObserverProxy,
												subjects:ISubjects):void
		{
			if(metadatas == null && metadatas.length == 0)
			{
				return ;
			}
			var metadata:Metadata = null;
			var notice:String = null;
			for each (var container:MetadataContainer in metadatas) 
			{
				//查看是否有Notice标签
				metadata = container.getMetadata(MetadataConst.NOTICE_METADATA);
				if(metadata != null)
				{
					if(metadata.firestArg == null)
					{
						if(container is Variable)
						{
							notice = Variable(container).getValue();
						}
						else
						{
							notice = container.name;
						}
					}
					else
					{
						notice = metadata.firestArg.value;
					}
					//作为主题添加观察者
					subjects.addObserver(notice,mediatorProxy);
					viewBean.addObserver(notice,mediatorProxy);
				}
			}
		}
		private function onViewInitEvent(event:InitViewMediatorEvent):void
		{
			var initViewMediator:InitViewMediator = event.target as InitViewMediator;
			initViewMediator.removeEventListener(InitViewMediatorEvent.INIT_OVER,onViewInitEvent);
			initViewList.add(event.viewBean);
			if(initViewList.size() == initCount)
			{
				//处理完成事件
				//全部完成了
				onComplete();
			}
		}
	}
}
